using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using HtmlAgilityPack;

namespace WhySoSeries
{
    public enum DataExtractionMode
    {
        AllEpisodes,
        LastEpisodes
    }

    public abstract class SeriesDataExtractor
    {
        public Series Series { get; private set; }
        protected HtmlDocument document;

        protected SeriesDataExtractor(string link)
        {
            this.Series = new Series(link);
        }

        protected SeriesDataExtractor(Series series)
        {
            this.Series = series;
        }

        protected abstract HtmlDocument GetSeriesHtmlDocument(string link, DataExtractionMode mode);
        protected abstract List<HtmlNode> GetEpisodeElements();
        protected abstract string GetSeriesName();
        protected abstract Episode GetEpisodeByHtmlNode(HtmlNode node, int index);

        public void ExtractAllInfo()
        {
            this.document = GetSeriesHtmlDocument(this.Series.Link, DataExtractionMode.AllEpisodes);
            this.Series.Name = GetSeriesName();
            int i = 0;
            foreach(HtmlNode node in GetEpisodeElements())
                this.Series.AddEpisode(GetEpisodeByHtmlNode(node, i++));
        }

        public List<Episode> UpdateEpisodes(Series series)
        {
            //Load page
            this.document = GetSeriesHtmlDocument(this.Series.Link, DataExtractionMode.LastEpisodes);

            //Get all episodes
            List<Episode> episodes = GetEpisodeElements().Select((node,i) => GetEpisodeByHtmlNode(node, i)).ToList();

            //Filter episodes
            Episode lastEpisode = series.GetSeasons().Last().GetEpisodes().Last();
            List<Episode> newEpisodes = (from ep in episodes
                                         where
                                             ((ep.Season.SeasonNumber > lastEpisode.Season.SeasonNumber) ||
                                              (ep.Season.SeasonNumber == lastEpisode.Season.SeasonNumber &&
                                               ep.EpisodeNumber > lastEpisode.EpisodeNumber))
                                         select ep).ToList();

            //Add new episodes
            foreach (Episode episode in newEpisodes)
                series.AddEpisode(episode);
            return newEpisodes;
        }
    }
}